package com.hongyun.tms.web.controller;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Maps;
import com.hongyun.tms.common.dto.SysFileDTO;
import com.hongyun.tms.common.enums.BizCode;
import com.hongyun.tms.common.enums.FileUploadBusinessTypeEnum;
import com.hongyun.tms.common.po.SysFilePO;
import com.hongyun.tms.domain.AjaxResult;
import com.hongyun.tms.exception.BusinessRuntimeException;
import com.hongyun.tms.service.SysFileService;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/internal/file")
public class FileController {

    @Autowired
    private SysFileService fileService;

    // 文件保存路径（可以通过配置文件进行配置）
    @Value("${file.upload-dir}")
    private String fileUploadDir;

    @ApiOperation("文件上传")
    @SneakyThrows
    @PostMapping("/upload")
    @ResponseBody
    public AjaxResult uploadFiles(@RequestParam("fileArray") MultipartFile[] fileArray,
                                  @RequestParam("businessType") String businessType) {
        List<UploadDisplay> files = new ArrayList<>();
        List<SysFileDTO> insertFileList = new ArrayList<>();

        //枚举中不包含时
        if (!FileUploadBusinessTypeEnum.valid(businessType)) {
            return AjaxResult.fail("不支持的业务类型" + businessType);
        }

        for (MultipartFile file : fileArray) {
            // 获取原始文件名
            String originalFileName = file.getOriginalFilename();
            if (StringUtils.isBlank(originalFileName)) {
                throw new BusinessRuntimeException(BizCode.BIZ_ERROR, "文件名不能为空");
            }


            // 获取文件扩展名
            String fileExtension = "";
            int dotIndex = originalFileName.lastIndexOf(".");
            if (dotIndex > 0) {
                fileExtension = originalFileName.substring(dotIndex);
            }

            // 生成新的文件名：yyyyMMdd_HHmmssSSS_文件名.后缀
            String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
            String newFileName = timestamp + "_" + originalFileName.substring(0, dotIndex) + fileExtension;

            // 保存文件到fileUploadDir下
            Path targetLocation = Paths.get(fileUploadDir).resolve(newFileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);

            // 生成文件下载的URL.  http://localhost:8081/api/internal/file/download/20240903091735378_b.png
            String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                    .path("/api/internal/file/download/")
                    .path(newFileName)
                    .toUriString();

            long newFileId = IdWorker.getId();
            // 构建 SysFileDTO 对象
            SysFileDTO sysFilePo = new SysFileDTO();
            sysFilePo.setId(newFileId);
            sysFilePo.setBusinessType(businessType);
            sysFilePo.setFilePath(fileDownloadUri);
            sysFilePo.setFileSaveName(newFileName);
            sysFilePo.setFileName(originalFileName);
            sysFilePo.setFileSuffix(fileExtension.substring(1));
            sysFilePo.setCreateTime(new Date());
            insertFileList.add(sysFilePo);


            //上传成功后的回显内容
            UploadDisplay uploadDisplay = new UploadDisplay()
                    .setFileName(originalFileName)
                    .setFileSuffix(fileExtension.substring(1))
                    .setFileDownloadUri(fileDownloadUri)
                    .setId(newFileId);
            files.add(uploadDisplay);
        }

        // 保存文件信息到数据库
        fileService.save(insertFileList);

        //兼容以前前端的格式，所以额外用一个Map
        Map<String, List<UploadDisplay>> rtnMap = Maps.newHashMap();
        rtnMap.put("files", files);
        return AjaxResult.success(rtnMap);
    }

    /**
     * 上传成功后返回给前端的内容
     */
    @Data
    @Accessors(chain = true)
    public static class UploadDisplay {
        @ApiModelProperty(value = "文件id")
        private Long id;

        @ApiModelProperty(value = "文件名")
        private String fileName;
        @ApiModelProperty(value = "后缀名，如.gif")
        private String fileSuffix;

        @ApiModelProperty(value = "下载URL")
        private String fileDownloadUri;
    }

    /**
     * 根据上传后返回的url和id信息，根据id返回你的文件
     *
     * @param id fileId
     * @return file
     * @throws MalformedURLException e
     */
    @GetMapping("/download/{id}")
    public ResponseEntity<Resource> downloadFile(@PathVariable String id) throws MalformedURLException {
        SysFilePO fileById = fileService.getFileById(Long.valueOf(id));
        Path filePath = Paths.get(fileUploadDir).resolve(fileById.getFileSaveName()).normalize();
        Resource resource = new UrlResource(filePath.toUri());

        if (!resource.exists()) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok()
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                .body(resource);
    }

    /**
     * 文件预览（主要针对图片、PDF等可以直接在浏览器中显示的文件，你可以用来测试）
     * 示例：http://localhost:8081/api/internal/file/preview/20240902181512048_b.png
     *
     * @param fileName 上传后返回的文件名
     * @return file 预览
     * @throws MalformedURLException
     */
    @GetMapping("/preview/{fileName}")
    public ResponseEntity<Resource> previewFile(@PathVariable String fileName) throws MalformedURLException {
        Path filePath = Paths.get(fileUploadDir).resolve(fileName).normalize();
        Resource resource = new UrlResource(filePath.toUri());

        if (!resource.exists()) {
            return ResponseEntity.notFound().build();
        }

        String contentType = "application/octet-stream";
        try {
            contentType = Files.probeContentType(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(contentType))
                .body(resource);
    }
}
